package ctrl;

import javax.servlet.http.HttpSession;

import model.LoginCredentials;
import model.Person;
import model.SimpleMail;
import model.TypStatus;

import org.apache.log4j.Logger;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.servlet.ModelAndView;

import dao.PersonDao;
import dao.PersonDeleteException;
import dao.PersonExistsException;
import dao.TypStatusDao;

@Controller
@SessionAttributes("email")
public class PersonController {
	private static Logger log = Logger.getLogger(PersonController.class);
	private PersonDao personDao = null;
	private LoginCredentials loginCredentials = null;
	private TypStatusDao typStatusDao = null;

	public void setPersonDao(PersonDao personDao) {
		this.personDao = personDao;
	}

	public void setLoginCredentials(LoginCredentials loginCredentials) {
		this.loginCredentials = loginCredentials;
	}

	public void setTypStatusDao(TypStatusDao typStatusDao) {
		this.typStatusDao = typStatusDao;
	}

	@RequestMapping(value = "/Login.html")
	public ModelAndView login() {
		log.info("Login");
		ModelAndView mv = new ModelAndView();
		mv.addObject("title", "Login");
		mv.addObject("message", "Anmeldung");
		mv.addObject("file", "login.jsp");
		mv.setViewName("home");
		return mv;
	}

	@RequestMapping(value = "/changeUserDataGlobal.html")
	public ModelAndView changeUserDataGlobal() {
		ModelAndView mv = new ModelAndView();
		mv.addObject("title", "Login");
		mv.addObject("message", "Anmeldung");
		mv.addObject("file", "changeUserDataGlobal.jsp");
		mv.setViewName("home");
		return mv;
	}

	/**
	 * Ändern des Status für den angemeldeten Benutzer
	 * 
	 * @return
	 */

	@RequestMapping(value = "/changeState.html")
	public ModelAndView changeState() {
		ModelAndView mv = new ModelAndView();
		mv.addObject("title", "Angebote");
		mv.addObject("message", "Status ändern");
		mv.addObject("file", "changeState.jsp");
		mv.setViewName("home");
		Person p = personDao.findById(loginCredentials.getId());
		mv.addObject("person", p);
		mv.addObject("typStati", typStatusDao.findAll());

		return mv;
	}

	/**
	 * Anzeigen der Angebote auf der Karte
	 */

	@RequestMapping(value = "/Angebote.html")
	public ModelAndView angebote() {
		ModelAndView mv = new ModelAndView();
		mv.addObject("title", "Angebote");
		mv.addObject("message", "Alle Anzeigen");
		mv.addObject("file", "list-personen.jsp");
		mv.setViewName("home");
		mv.addObject("typStati", typStatusDao.findAll());

		return mv;
	}

	/**
	 * 
	 * @param pId
	 * @param stateCouch
	 * @param stateInternet
	 * @param stateZeigeStadt
	 * @param stateParkplatz
	 * @return
	 */
	// saveState.html
	@RequestMapping(value = "/saveState.html")
	public ModelAndView saveState(@RequestParam("id") String pId,
			@RequestParam("stateCouch") String stateCouch,
			@RequestParam("stateInternet") String stateInternet,
			@RequestParam("stateZeigeStadt") String stateZeigeStadt,
			@RequestParam("stateParkplatz") String stateParkplatz) {
		ModelAndView mv = new ModelAndView();
		String msg = "", errormsg = "";
		mv.addObject("title", "Angebote");
		mv.addObject("message", "Status ändern");
		mv.addObject("file", "changeState.jsp");
		mv.setViewName("home");
		mv.addObject("typStati", typStatusDao.findAll());

		Person p = personDao.findById(Integer.parseInt(pId));
		p.setStateCouch(new TypStatus(typStatusDao.findById(Integer
				.parseInt(stateCouch))));
		p.setStateInternet(new TypStatus(typStatusDao.findById(Integer
				.parseInt(stateInternet))));
		p.setStateParkplatz(new TypStatus(typStatusDao.findById(Integer
				.parseInt(stateParkplatz))));
		p.setStateZeigeStadt(new TypStatus(typStatusDao.findById(Integer
				.parseInt(stateZeigeStadt))));

		mv.addObject("person", p);

		try {
			personDao.saveStati(p);
			msg = "Status erfolgreich abgeändert";
		} catch (Exception e) {
			errormsg = e.getMessage();
		}

		mv.addObject("msg", msg);
		mv.addObject("errormsg", errormsg);

		return mv;
	}

	@RequestMapping(value = "/changeUserData.html")
	public ModelAndView changeUserData() {
		ModelAndView mv = new ModelAndView();
		mv.addObject("title", "Stammdaten");
		mv.addObject("message", "Benutzerdaten ändern");
		mv.addObject("mode", "change");
		mv.addObject("file", "saveUser.jsp");
		mv.addObject("isLogUserAdmin", loginCredentials.getIsAdmin());
		mv.setViewName("home");

		Person p = personDao.findById(loginCredentials.getId());
		mv.addObject("person", p);
		mv.addObject("typStati", typStatusDao.findAll());
		mv.addObject("errormsg", "");

		return mv;
	}

	@RequestMapping(value = "/changeUserDataAdmin.html")
	public ModelAndView changeUserDataAdmin(@RequestParam("id") String pId) {
		ModelAndView mv = new ModelAndView();
		mv.addObject("title", "Stammdaten");
		mv.setViewName("home");

		if (loginCredentials.getIsAdmin()) {
			mv.addObject("message", "Benutzerdaten ändern");
			mv.addObject("mode", "change");
			mv.addObject("file", "saveUser.jsp");
			mv.addObject("isLogUserAdmin", loginCredentials.getIsAdmin());

			Person p = personDao.findById(Integer.parseInt(pId));
			mv.addObject("person", p);
			mv.addObject("typStati", typStatusDao.findAll());
			mv.addObject("errormsg", "");
		} else {
			mv.addObject("message",
					"Sie sind nicht berechtigt den Benutzer zu ändern");
		}

		return mv;
	}

	@RequestMapping(value = "/changePWD.html")
	public ModelAndView changePWD() {
		log.info("changePWD");
		ModelAndView mv = new ModelAndView();
		mv.addObject("title", "Passwort ändern");
		mv.addObject("file", "changePWD.jsp");
		mv.addObject("email", loginCredentials.getUsername());
		mv.setViewName("home");
		return mv;
	}

	@RequestMapping(value = "/SavePWD.html")
	public ModelAndView savePWD(@RequestParam("email") String email,
			@RequestParam("pwdalt") String pwdalt,
			@RequestParam("pwdneu1") String pwdneu1,
			@RequestParam("pwdneu2") String pwdneu2) {
		ModelAndView mv = new ModelAndView();
		log.info("SavePWD");
		mv.addObject("title", "Passwort ändern");
		mv.addObject("file", "changePWD.jsp");

		String errormsg = "", msg = "";
		Person p = new Person();

		if (!pwdneu1.equals(pwdneu2)) { // Stimmen das neue Passwort mit der
										// Wiederholung ueberein
			errormsg = "Das neue Passwort stimmt nicht mit der Wiederholungseingabe überein";
		}

		if (errormsg == "") { // Ist das Kennwort mindestens 8 Zeichen lang
			if (pwdneu1.length() < 8) {
				errormsg = "Das neue Kennwort muss mindestens 8 Zeichen lang sein";
			}
		}

		if (errormsg == "") {
			p = personDao.checkLogin(email, pwdalt);
			if (p.getId() == 0) { // Kein Match; Passwort u. Benutzer passen
									// nicht zusammen
				errormsg = "Passwort stimmt mit dem Benutzernamen nicht überein";
			}
		}

		if (errormsg == "") {
			try {
				p.setPWD(pwdneu1);
				personDao.save(p);
				msg = "Passwort erfolgreich abgeaendert";
				pwdalt = "";
				pwdneu1 = "";
				pwdneu2 = "";
			} catch (PersonExistsException e) {
				errormsg = e.getMessage();
			}
		}

		mv.addObject("email", email);
		mv.addObject("pwdalt", pwdalt);
		mv.addObject("pwdneu1", pwdneu1);
		mv.addObject("pwdneu2", pwdneu2);

		mv.addObject("errormsg", errormsg);
		mv.addObject("msg", msg);
		mv.setViewName("home");
		return mv;
	}

	/**
	 * Anmeldung an das System mit anschließender Begrüßung
	 * 
	 * @param email
	 *            Erwartet eine gültige Emailadresse
	 * @param pwd
	 *            Erwartet das Passwort
	 * @param session
	 *            Werte werden in die Session geschrieben
	 * @return
	 */

	@RequestMapping(value = "/LoginUser.html", method = RequestMethod.POST)
	public ModelAndView loginUser(@RequestParam("email") String email,
			@RequestParam("pwd") String pwd, HttpSession session) {
		log.info("Login");
		ModelAndView mv = new ModelAndView();
		String msg = "";

		mv.addObject("title", "Login");
		mv.addObject("message", "Anmeldung");
		mv.addObject("file", "login.jsp");
		mv.setViewName("home");

		Person p = new Person();
		p = personDao.checkLogin(email, pwd);

		if (p.getId() != 0) {
			msg = "Anmeldung war erfolgreich. Hallo " + p.getNachname() + " "
					+ p.getVorname();
			// Setzen der Attribute in der Session
			session.setAttribute("username", email);
			session.setAttribute("vorname", p.getVorname());
			session.setAttribute("nachname", p.getNachname());
		} else {
			msg = "Anmeldung fehlgeschlagen";
			session.setAttribute("username", null);
			session.setAttribute("vorname", null);
			session.setAttribute("nachname", null);
		}
		loginCredentials.setId(p.getId());
		loginCredentials.setUsername(p.getEMail());
		loginCredentials.setIsAdmin(p.getIsAdmin());

		mv.addObject("email", email);
		mv.addObject("pwd", "");
		mv.addObject("msg", msg);

		return mv;
	}

	/**
	 * Meldet den Benutzer ab und zerstört die Session
	 * 
	 * @return
	 */

	@RequestMapping(value = "/Abmelden.html")
	public ModelAndView abmelden(HttpSession session) {
		log.info("Abmelden");
		ModelAndView mv = new ModelAndView();

		mv.addObject("title", "Couchsurfing");
		mv.addObject("message",
				"Schlafplatz, Stadtführung, Parkplatz, Internetzugang");
		mv.addObject("file", "/view/home.htm");
		mv.setViewName("home");

		session.setAttribute("username", null);
		session.setAttribute("vorname", null);
		session.setAttribute("nachname", null);

		loginCredentials.setId(0);
		loginCredentials.setUsername("");
		loginCredentials.setIsAdmin(false);

		return mv;
	}

	@RequestMapping(value = "/registerUser.html")
	public ModelAndView registerUser() {
		log.info("RegisterUser");
		ModelAndView mv = new ModelAndView();
		Person person = new Person();

		mv.addObject("title", "Register");
		mv.addObject("message", "Neuer User");
		mv.addObject("file", "saveUser.jsp");
		mv.addObject("isLogUserAdmin", loginCredentials.getIsAdmin());
		mv.addObject("typStati", typStatusDao.findAll());
		mv.addObject("errormsg", "");
		mv.addObject("person", person);
		mv.setViewName("home");

		return mv;
	}

	/*
	 * @RequestMapping(value="/SavePerson.html", method=RequestMethod.POST)
	 * public String save(Person person, Model model) { if (person.getCreated()
	 * == null) { person.setCreated(new Date()); } Person result =
	 * personDao.save(person); // set id from create if (person.getId() == null)
	 * { person.setId(result.getId()); } model.addAttribute("statusMessageKey",
	 * "person.form.msg.success"); return "redirect:AllePersonen.html"; }
	 */

	@RequestMapping(value = "/SaveUser.html", method = RequestMethod.POST)
	public ModelAndView save(@RequestParam("id") String id,
			@RequestParam("name") String name,
			@RequestParam("vname") String vname,
			@RequestParam("adresse") String adresse,
			@RequestParam("plz") String plz, @RequestParam("ort") String ort,
			@RequestParam("email") String email,
			@RequestParam(value = "isAdmin", required = false) String isAdmin,
			@RequestParam("stateCouch") String stateCouch,
			@RequestParam("stateInternet") String stateInternet,
			@RequestParam("stateZeigeStadt") String stateZeigeStadt,
			@RequestParam("stateParkplatz") String stateParkplatz) {
		ModelAndView mv = new ModelAndView();
		Person p = new Person();
		String errormsg = "", msg = "";
		boolean modeNewUser = false;

		// Pruefe, ob alle Felder ausgefuellt wurden
		if (name == "" || vname == "" || adresse == "" || plz == ""
				|| ort == "" || email == "") {
			errormsg = "Bitte die rot markierten Pflichtfelder ausfuellen";
		} else {
			// Pruefe, ob gueltige E-Mail-Adresse eingetragen wurde

			// http://regexlib.com/%28X%281%29A%28sgb59rXI41MGi9oL257u3ZctOXWq4eaOj0gJ5hc8qiFOzINK2cCXmD6ZEqcpF9DYVIOkiqVxxAT_0rDZ-1-vvIe-X7TRzZ4wxUkQXSUvFCmPORj79gHykhDd4KlXU5G975bBG_Fr6R0oJ73nASbYFA1X5bH6jgV_SsuGvW8r--i9_-RQQNBD-d5-9U_OaKJC0%29%29/CheatSheet.aspx
			if (!email.matches("^[\\w-\\.]+@([\\w-]+\\.)+[\\w-]{2,4}$")) {
				// . any character
				// \w = [a-zA-Z_0-9]
				// $ End of String

				errormsg = "Bitte gueltige E-Mail-Adresse eingeben";
				mv.addObject("errEmail", "1");
			}
		}

		// Werte muessen gesetzt werden, wegen Merkfunktion
		if (name != "") {
			p.setNachname(name);
		}

		if (vname != "") {
			p.setVorname(vname);
		}

		if (adresse != "") {
			p.setAdresse(adresse);
		}
		if (plz != "") {
			p.setPLZ(plz);
		}
		if (ort != "") {
			p.setOrt(ort);
		}
		if (email != "") {
			p.setEMail(email);
		}

		if (isAdmin != null) {
			p.setIsAdmin(Boolean.parseBoolean(isAdmin));
		}

		p.setStateCouch(new TypStatus(typStatusDao.findById(Integer
				.parseInt(stateCouch))));
		p.setStateInternet(new TypStatus(typStatusDao.findById(Integer
				.parseInt(stateInternet))));
		p.setStateParkplatz(new TypStatus(typStatusDao.findById(Integer
				.parseInt(stateParkplatz))));
		p.setStateZeigeStadt(new TypStatus(typStatusDao.findById(Integer
				.parseInt(stateZeigeStadt))));

		if (!(id.equals("0") || id.equals(""))) {
			p.setId(Integer.parseInt(id));
			mv.addObject("mode", "change");
			mv.addObject("title", "Stammdaten");
			mv.addObject("message", "Benutzerdaten ändern");
		}

		if (errormsg != "") {
			mv.addObject("file", "saveUser.jsp");
		} else {
			if (id.equals("0") || id.equals("")) {
				// Neuen Benutzer anlegen
				mv.addObject("title", "Register");
				mv.addObject("message", "Neuer User");

				// Generiere Passwort fuer Benutzer
				p.generateRandomPWD();

				modeNewUser = true;
			} else {
				// Benutzer aendern
				mv.addObject("title", "Stammdaten");
				mv.addObject("message", "Benutzerdaten ändern");

				Person tmp = personDao.findById(Integer.parseInt(id));
				p.setPWD(tmp.getPWD());
				p.setId(tmp.getId());
			}

			Person result;
			try {
				result = personDao.save(p);
				p.setId(result.getId());

				if (modeNewUser) {
					msg = "User erfolgreich anlegt. Zugangsdaten werden per Mail an "
							+ email
							+ " zugesendet. (PWD da E-Mailversand deaktiv: "
							+ p.getPWD() + " )";

					SimpleMail sm = new SimpleMail();
					try {
						String inhalt = "Vielen Dank fuer die Anmeldung am Couchsurfing-Portal (http://localhost:8080/couchsurfing/Login.html)\n\n";
						inhalt += "Ihre Zugangsdaten lauten wie folgt:\n";
						inhalt += "\tBenutzername: " + p.getEMail() + "\n";
						inhalt += "\tPasswort: " + p.getPWD() + "\n\n";
						inhalt += "Mit freundlichen Gruessen\n";
						inhalt += "  Ihr Service-Team";

						sm.sendMessage(email, inhalt);

						mv.addObject("file", "login.jsp");
						mv.addObject("email", p.getEMail());
					} catch (Exception e) {
						errormsg = msg + "\n" + e.getMessage();
						mv.addObject("file", "saveUser.jsp");
					}
				} else {
					mv.addObject("mode", "change");
					msg = "Benutzerdaten erfolgreich abgeändert";
					mv.addObject("file", "saveUser.jsp");

					// Wenn man sich sein eigenes Admin-Recht entfernt, somit
					// ist es gleich wirksam
					if (p.getId() == loginCredentials.getId()) {
						loginCredentials.setIsAdmin(p.getIsAdmin());
					}
				}
			} catch (PersonExistsException e) {
				errormsg = e.getMessage();
				mv.addObject("file", "saveUser.jsp");
				mv.addObject("errEmail", "1");
			}
		}

		mv.addObject("typStati", typStatusDao.findAll());
		mv.addObject("isLogUserAdmin", loginCredentials.getIsAdmin());
		mv.addObject("errormsg", errormsg);
		mv.addObject("msg", msg);
		mv.addObject("person", p);
		mv.setViewName("home");

		return mv;
	}

	/* Schneeberger - Funktionen */
	@RequestMapping(value = "/EditPerson.html", method = RequestMethod.GET)
	public ModelAndView edit2(@RequestParam(required = false) Integer id) {
		ModelAndView mv = new ModelAndView();
		if (id == null) {
			mv.addObject(new Person());
		} else {
			mv.addObject(personDao.findById(id));
		}

		mv.setViewName("edit-person");
		return mv;
	}

	/**
	 * <p>
	 * Saves a person.
	 * </p>
	 * 
	 * <p>
	 * Expected HTTP POST and request '/SavePerson.html'.
	 * </p>
	 * 
	 * @return
	 */
	/**
	 * <p>
	 * Deletes a person.
	 * </p>
	 * 
	 * <p>
	 * Expected HTTP POST and request '/LoeschePerson.html'.
	 * </p>
	 */
	@RequestMapping(value = "/LoeschePerson.html", method = RequestMethod.GET)
	public ModelAndView deleteUserSingle(Person person) {
		ModelAndView mv = new ModelAndView();
		String msg = "", errormsg = "";

		try {
			personDao.delete(person);
			mv = findAll();
		} catch (Exception e) {
			if (e.getClass() == PersonDeleteException.class) {
				mv = findAll();
				mv.addObject("delID", person.getId());
				mv.addObject("errormsgUserRef", e.getMessage());
			} else {
				errormsg = e.getMessage();
			}
		}

		mv.addObject("errormsg", errormsg);
		mv.addObject("msg", msg);
		return mv;
		// return "redirect:AllePersonen.html";
	}

	@RequestMapping(value = "/LoeschePersonUndRef.html", method = RequestMethod.GET)
	public ModelAndView deleteUserAll(
			@RequestParam(value = "delID", required = false) String id) {
		ModelAndView mv = new ModelAndView();
		String msg = "", errormsg = "";

		if (loginCredentials.getIsAdmin()) {
			personDao.deleteInkRef(Integer.parseInt(id));
			mv.addObject("errormsg", errormsg);
		} else {
			mv.addObject("errormsg",
					"Sie sind nicht berechtig eine Person zu löschen");
		}
		mv = findAll();
		mv.addObject("msg", msg);
		return mv;
	}

	/**
	 * Searches for all persons and returns them in a Collection. Expected HTTP
	 * GET and request '/AllePersonen.html'.
	 * 
	 */
	@RequestMapping(value = "/AllePersonen.html", method = RequestMethod.GET)
	public ModelAndView findAll() {
		ModelAndView mv = new ModelAndView();
		mv.addObject("title", "Angebote");
		mv.addObject("message", "");
		mv.addObject("isLogUserAdmin", loginCredentials.getIsAdmin());
		mv.addObject("file", "list-personen.jsp");
		mv.addObject("personen", personDao.findAllPlusNote());
		mv.setViewName("home");
		return mv;
	}
}
